// ignore_for_file: prefer_typing_uninitialized_variables

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:web_socket_channel/io.dart';

import '../model/im/socket_params_model.dart';

class WebSocketManager {
  // static const String _websocketUrl = 'ws://124.222.224.186:8800'; // 你的 WebSocket 服务器地址
  IOWebSocketChannel? _channel;
  String? url;
  String? roomId;
  bool isConnected = false; // 是否连接
  bool isConnecting = false; // 是否正在连接中
  WebSocketManager({
    required String this.url,
    required String this.roomId,
    required this.socketCloseCallBack,
    required this.requestSuccessCallBack,
    required this.responseConnentCallBack,
    required this.responseChoosingCallBack,
    required this.videoStartCallBack,
    required this.videoEndCallBack,
    required this.reciveTxtCallBack,
    required this.canCallTimeCallBack,
    required this.accountcoinsCallBack,
    required this.autoHangUpCallBack,
  });

  VoidCallback socketCloseCallBack;
  VoidCallback requestSuccessCallBack;
  VoidCallback responseConnentCallBack;
  var responseChoosingCallBack;
  var videoStartCallBack;
  var videoEndCallBack;
  var reciveTxtCallBack;
  var canCallTimeCallBack;
  var accountcoinsCallBack;
  var autoHangUpCallBack;

  void connect() {
    _channel = IOWebSocketChannel.connect(url!);
    debugPrint('连接成功，可以立刻登录你公司后台的服务器了，还有开启心跳');
    if (!isConnected && !isConnecting) {
      isConnecting = true;
      _channel = IOWebSocketChannel.connect('$url/$roomId');
      _channel?.stream.listen(
        (message) {
          // 处理接收到的消息
          debugPrint('处理接收到的消息: $message');
          String messageStr = message.toString();
          bool endsWithDoubleAtSign = messageStr.endsWith('@@');
          if (endsWithDoubleAtSign) {
            messageStr = messageStr.substring(0, messageStr.length - 2);
            Map<String, dynamic> resultMap = jsonDecode(messageStr);
            if (resultMap['method'] == 'heartbeat') {
              return;
            }
            SocketParmaModel socketParmaModel =
                SocketParmaModel.fromJson(resultMap);
            if (socketParmaModel.code == 0) {
              debugPrint('消息末尾包含了@@,这里重新处理,重新处理成功:${socketParmaModel.code}');
              if (socketParmaModel.method == 'request') {
                // 主叫方连接成功
                requestSuccessCallBack();
              } else if (socketParmaModel.method == 'response') {
                // 被叫方连接成功
                debugPrint('被叫方连接成功');
                responseConnentCallBack();
              } else if (socketParmaModel.method == 'updatetip') {
                // 主叫方更新提示信息
                debugPrint('主叫方更新提示信息');
                responseChoosingCallBack(socketParmaModel.socketData?.tip);
              } else if (socketParmaModel.method == 'startvideo') {
                // 接通视频通话
                debugPrint('接通视频通话');
                videoStartCallBack(socketParmaModel.socketData);
              } else if (socketParmaModel.method == 'notice') {
                // 文字交互
                debugPrint('文字交互');
                reciveTxtCallBack(socketParmaModel.socketData?.content);
              } else if (socketParmaModel.method == 'hangup') {
                // 视频通话结束
                debugPrint('视频通话结束');
                if (roomId == socketParmaModel.socketData?.roomid.toString()) {
                  // 判断挂断消息是否是当前房间
                  videoEndCallBack(socketParmaModel.socketData?.type);
                }
              } else if (socketParmaModel.method == 'cancalltime') {
                // 剩余通话时长
                debugPrint('剩余通话时长');
                canCallTimeCallBack(socketParmaModel.socketData?.tip);
                accountcoinsCallBack(socketParmaModel.socketData?.coin);
              }
            } else {
              if (socketParmaModel.message != '') {
                EasyLoading.showToast(socketParmaModel.message ?? '');
              }
            }
          }
        },
        onDone: () {
          // WebSocket 连接关闭时的处理
          debugPrint('WebSocket 连接关闭时的处理.');
          isConnected = false;
          isConnecting = false;
          close();
          socketCloseCallBack();
        },
        onError: (error) {
          // 处理连接错误
          debugPrint('处理连接错误: $error');
          isConnected = false;
          isConnecting = false;

          // 重新连接
          if (!isConnecting) {
            // 延时一定时间后重连，可以根据实际情况调整延时时间
            Future.delayed(const Duration(seconds: 10), () {
              debugPrint('连接失败,10秒后重新连接');
            });
          }
        },
      );
      isConnected = true;
      isConnecting = false;
      // 启动心跳机制
      startHeartbeat();
    }
  }

  /// // 重新连接
  void resetConnect() {
    if (!isConnecting) {
      // 延时一定时间后重连，可以根据实际情况调整延时时间
      Future.delayed(const Duration(seconds: 10), () {
        debugPrint('连接失败,10秒后重新连接');
        connect();
      });
    }
  }

  /// 发送心跳
  void startHeartbeat() {
    const Duration heartbeatInterval = Duration(seconds: 10);
    Timer.periodic(heartbeatInterval, (Timer timer) {
      if (isConnected && _channel != null) {
        // 发送心跳数据
        sendHeartBeat();
      } else {
        // 如果连接已断开，则停止心跳
        timer.cancel();
      }
    });
  }

  void send(String message) {
    if (isConnected && _channel != null) {
      // 发送消息
      _channel!.sink.add(message);
    } else {
      debugPrint('WebSocke已经关闭,无法发送消息');
    }
  }

  void close() {
    // 关闭 WebSocket 连接
    _channel?.sink.close();

    isConnected = false;
    isConnecting = false;
  }

  void sendData(List<int> data) {
    if (isConnected && _channel != null) {
      // 发送消息
      _channel!.sink.add(data);
    } else {
      debugPrint('WebSocke已经关闭,无法发送消息');
    }
  }

  /// 发送心跳
  void sendHeartBeat() {
    debugPrint('发送心跳');
    Map map = {
      'method': 'heartbeat',
      'data': {'room_id': roomId}
    };
    String jsonString = jsonEncode(map);
    List<int> data = utf8.encode(jsonString);
    sendData(data);
  }

  /// 发送取消
  void sendCancel() {
    debugPrint('发送取消');
    Map map = {
      'method': 'cancel',
      'data': {'room_id': roomId}
    };
    String jsonString = jsonEncode(map);
    List<int> data = utf8.encode(jsonString);
    sendData(data);
  }

  void sendRefuse() {
    Map map = {
      'method': 'refuse',
      'data': {'room_id': roomId}
    };
    String jsonString = jsonEncode(map);
    List<int> data = utf8.encode(jsonString);
    sendData(data);
  }

  void sendAgree() {
    Map map = {
      'method': 'agree',
      'data': {'room_id': roomId}
    };
    String jsonString = jsonEncode(map);
    List<int> data = utf8.encode(jsonString);
    sendData(data);
  }

  void sendHangup() {
    Map map = {
      'method': 'hangup',
      'data': {'room_id': roomId}
    };
    String jsonString = jsonEncode(map);
    List<int> data = utf8.encode(jsonString);
    sendData(data);
  }
}
